﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using MYTech.Utils;

namespace MYTech.Oracle
{
    /// <summary>
    /// 分区类型
    /// </summary>
    public enum PartitionType : uint
    {
        /// <summary>
        /// 小时分区
        /// </summary>
        Hour,
        /// <summary>
        /// 天分区
        /// </summary>
        Day
    }

    public class TablePartition
    {
        public string TableName { get; set; }
        public bool Partitoned { get; set; }
        private PartitionType type;
        public PartitionType Type { get { return type; } }
        private DateTime maxPartitionTime;

        public DateTime MaxPartitionTime
        {
            get
            {
                DateTime time = DateTime.Now.Date;
                if (this.maxPartitionTime < time)
                    return time;
                return maxPartitionTime;
            }
        }

        private List<Partition> partitions;
        public Partition[] Partitions
        {
            get
            {
                if (partitions == null)
                    return null;
                partitions.Sort((x, y) => DateTime.Compare(x.Time, y.Time));
                return partitions.ToArray();
            }
        }

        public TablePartition(string tableName, bool partitoned)
        {
            this.TableName = tableName;
            this.Partitoned = partitoned;
        }

        private List<string> partitionNames;
        public TablePartition AddPartition(string partition_name)
        {
            if (partitionNames == null)
                partitionNames = new List<string>();
            if (!string.IsNullOrEmpty(partition_name))
                partitionNames.Add(partition_name);
            return this;
        }

        public string this[int count]
        {
            get
            {
                DateTime time;
                DateTime start;
                if (this.Type == PartitionType.Hour)
                {
                    time = this.MaxPartitionTime.AddHours(count);
                    start = time.AddHours(-1);
                }
                else
                {
                    time = this.MaxPartitionTime.AddDays(count);
                    start = time.AddDays(-1);
                }
                this.maxPartitionTime = time;
                return string.Format("alter table {0} add partition {0}_{1:yyMMddHHmm} values less than (TIMESTAMP' {2:yyyy-MM-dd HH:mm:ss}')", this.TableName, start, time);
            }
        }

        public List<string> this[DateTime start, DateTime end]
        {
            get
            {
                return null;
            }
        }

        public void Analyze()
        {
            if (Partitoned)
            {
                partitions = new List<Partition>();
                this.type = PartitionType.Day;
                DateTime maxTime = DateTime.MinValue;
                foreach (string partition in partitionNames)
                {
                    try
                    {
                        Partition _partition = new Partition(this.TableName, partition);
                        if (maxTime < _partition.Time)
                            maxTime = _partition.Time;
                        partitions.Add(_partition);
                        if (_partition.MinType == PartitionType.Hour)
                            this.type = PartitionType.Hour;
                    }
                    catch (Exception)
                    {
                    }
                }
                this.maxPartitionTime = maxTime;
            }
        }

        public override string ToString()
        {
            return string.Format("{0} {1}", this.TableName, this.Partitoned);
        }

        public int Compare(object y)
        {
            TablePartition _y = y as TablePartition;
            if (this.Partitoned == _y.Partitoned)
                return 0;
            else if (this.Partitoned && !_y.Partitoned)
                return -1;
            else
                return 1;
        }
    }
}
